//****************************************************
// Porman Project 2
// Filename: CVertexDeclObject.h
// Date: 2009/03/022
// Author: KengYu Lin
// Modify:
//****************************************************
#ifndef _CVERTEXDECLOBJECT_H
#define _CVERTEXDECLOBJECT_H
#include "CGLDef.h"
#include "CBaseObject.h"
#include <vector>

namespace Porman
{

namespace GL
{

class CVertexElementArray;

//------------------------------
// class SVertexElement
//------------------------------
struct SVertexElement
{
public:
    PGL_API SVertexElement( void ) : m_sSemantic(), m_iSemanticIndex(-1), m_iType(-1), m_iOffset(-1), m_iUsageIndex(-1) {}
    PGL_API SVertexElement( const char* pSemantic, int iSemanticIndex, EVertexEleType enumType, int iOffset, int iUsageIndex ) : m_sSemantic(pSemantic), m_iSemanticIndex(iSemanticIndex), m_iType(enumType), m_iOffset(iOffset), m_iUsageIndex(iUsageIndex) {}
    PGL_API SVertexElement( const SVertexElement& l ) { (*this) = l; }
    PGL_API SVertexElement& operator=( const SVertexElement& l ) { m_sSemantic = l.m_sSemantic; m_iSemanticIndex = l.m_iSemanticIndex; m_iType = l.m_iType; m_iOffset = l.m_iOffset; m_iUsageIndex = l.m_iUsageIndex; return (*this); }
    PGL_API virtual ~SVertexElement( void ) {}

    PGL_API bool isVaild( void ) { return (m_iOffset != -1 ? true : false); }

public:
    std::string m_sSemantic;
    int m_iSemanticIndex;
    int m_iType;
    int m_iOffset;
    int m_iUsageIndex;
};

//------------------------------
// class CVertexElementArray
//------------------------------
class CVertexElementArray
{
    friend class CVertexDeclObject;
public:
    PGL_API CVertexElementArray( void );
    PGL_API CVertexElementArray( const CVertexElementArray& l );
    PGL_API ~CVertexElementArray( void ) {}
    
    PGL_API CVertexElementArray& operator=( const CVertexElementArray& l );
    PGL_API inline void setVE( const char* pSemantic, int iSemanticIndex, EVertexEleType enumType, int iOffset, int iUsageIndex );
    PGL_API inline void setVE( SVertexElement& VE );
    PGL_API SVertexElement getVE( int iIndex );
    PGL_API int getNumOfVE( void );

protected:
    std::vector<SVertexElement> m_vectVEArray;
};

//------------------------------
// class CVertexDeclObject
//------------------------------
class CVertexDeclObject : public CBaseObject
{
    friend class CRenderDevice;
public:
    PGL_API virtual void setName( const char* pName ) { m_sName = std::string("VDecObj_") + std::string( pName ); }
    PGL_API CVertexElementArray getDecl( void ) { return m_VertexElements; }

protected:
    CVertexDeclObject( CRenderDevice* pDevice );
    virtual ~CVertexDeclObject( void );

    bool _processDataArray( SVertexElement* pVertexElementsArray );
    bool _processDataArray( CVertexElementArray* pVertexElementsArray );
    void _processData( SVertexElement& VElements );
    inline void _calculateSizeAndType( SVertexElement& VElements, int& iStride, int& iType );

protected:
    struct SData
    {
    public:
        SData( void ) : m_sSemantic(), m_iStride(0), m_iType(0), m_iOffset(0), m_iUsageIndex(0) {}

    public:
        std::string  m_sSemantic;
        int m_iStride;
        int m_iType;
        int m_iOffset;
        int m_iUsageIndex;
    };

protected:
    std::vector<SData> m_vectSData;
    CVertexElementArray m_VertexElements;
};

}//End namespace GL

}//End namespace Porman

#endif